﻿using System;
using System.Xml;
using SharePointOfView.SPReporting.Jobs;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;

namespace SharePointOfView.SPReporting.Samples.Jobs
{
    public class FarmStructureJob : GenericReportingJobDefinition
    {
        public FarmStructureJob() : base() { }

        public FarmStructureJob(string jobName, string jobDisplayName, string reportName, SPJobLockType lockType)
            : base(jobName, jobDisplayName, reportName, lockType)
        {
        }

        public override XmlDocument GatherData()
        {
            XmlDocument xmlDocument = new XmlDocument();

            xmlDocument.LoadXml("<Farm />");

            SPFarm localFarm = SPFarm.Local;

            // Servers
            XmlNode serversElt = xmlDocument.CreateNode(XmlNodeType.Element, "Servers", "");
            xmlDocument.DocumentElement.AppendChild(serversElt);
            foreach (SPServer server in localFarm.Servers)
            {
                // Create the Server node
                XmlNode serverElt = xmlDocument.CreateNode(XmlNodeType.Element, "Server", "");
                // Server Id
                XmlAttribute serverAttrId = xmlDocument.CreateAttribute("Id");
                serverAttrId.Value = server.Id.ToString();
                serverElt.Attributes.Append(serverAttrId);
                // Server Name
                XmlAttribute serverAttrName = xmlDocument.CreateAttribute("Name");
                serverAttrName.Value = server.Name;
                serverElt.Attributes.Append(serverAttrName);
                // Address
                XmlAttribute serverAttrAddress = xmlDocument.CreateAttribute("Address");
                serverAttrAddress.Value = server.Address;
                serverElt.Attributes.Append(serverAttrAddress);
                // Display Name
                XmlAttribute serverAttrDisplayName = xmlDocument.CreateAttribute("DisplayName");
                serverAttrDisplayName.Value = server.DisplayName;
                serverElt.Attributes.Append(serverAttrDisplayName);
                // Status
                XmlAttribute serverAttrStatus = xmlDocument.CreateAttribute("Status");
                serverAttrStatus.Value = server.Status.ToString();
                serverElt.Attributes.Append(serverAttrStatus);
                // NeedsUpgrade
                XmlAttribute serverAttrNeedsUpgrade = xmlDocument.CreateAttribute("NeedsUpgrade");
                serverAttrNeedsUpgrade.Value = server.NeedsUpgrade.ToString();
                serverElt.Attributes.Append(serverAttrNeedsUpgrade);
                // Version
                XmlAttribute serverAttrVersion = xmlDocument.CreateAttribute("Version");
                serverAttrVersion.Value = server.Version.ToString();
                serverElt.Attributes.Append(serverAttrVersion);
                // Append the Server node to "<Servers />"
                serversElt.AppendChild(serverElt);
            }

            // Web applications
            SPWebService webSvc = localFarm.Services.GetValue<SPWebService>();
            XmlNode webAppsElt = xmlDocument.CreateNode(XmlNodeType.Element, "WebApplications", "");
            xmlDocument.DocumentElement.AppendChild(webAppsElt);

            int webAppProgressStep = Convert.ToInt32(100 / (webSvc.WebApplications.Count + 1));
            foreach (SPWebApplication webApp in webSvc.WebApplications)
            {
                XmlNode webAppElt = xmlDocument.CreateNode(XmlNodeType.Element, "WebApplication", "");
                // Id
                XmlAttribute webAppAttrId = xmlDocument.CreateAttribute("Id");
                webAppAttrId.Value = webApp.Id.ToString();
                webAppElt.Attributes.Append(webAppAttrId);
                // Url
                XmlAttribute webAppAttrUrl = xmlDocument.CreateAttribute("Url");
                webAppAttrUrl.Value = webApp.AlternateUrls[0].Uri.ToString();
                webAppElt.Attributes.Append(webAppAttrUrl);
                // Create the <Sites /> node
                XmlNode sitesElt = xmlDocument.CreateNode(XmlNodeType.Element, "Sites", "");
                webAppElt.AppendChild(sitesElt);

                int siteProgressStep = Convert.ToInt32(webAppProgressStep / (webApp.Sites.Count + 1));
                int totalSiteProgress = 0;
                // For each site collections generate <Site />
                foreach (SPSite site in webApp.Sites)
                {
                    // Create the <Site /> node with all attributes
                    XmlNode siteElt = xmlDocument.CreateNode(XmlNodeType.Element, "Site", "");
                    // ID
                    XmlAttribute siteAttrId = xmlDocument.CreateAttribute("ID");
                    siteAttrId.Value = site.ID.ToString();
                    siteElt.Attributes.Append(siteAttrId);
                    // LastContentModifiedDate
                    XmlAttribute siteAttrModDate = xmlDocument.CreateAttribute("LastContentModifiedDate");
                    siteAttrModDate.Value = site.LastContentModifiedDate.ToString("s");
                    siteElt.Attributes.Append(siteAttrModDate);
                    // Url
                    XmlAttribute siteAttrUrl = xmlDocument.CreateAttribute("Url");
                    siteAttrUrl.Value = site.Url;
                    siteElt.Attributes.Append(siteAttrUrl);
                    // ContentDatabase
                    XmlAttribute siteAttrContentDatabase = xmlDocument.CreateAttribute("ContentDatabase");
                    siteAttrContentDatabase.Value = site.ContentDatabase.Name;
                    siteElt.Attributes.Append(siteAttrContentDatabase);

                    // Gather Site Usage
                    XmlNode siteUsageElt = xmlDocument.CreateNode(XmlNodeType.Element, "Usage", "");
                    // Bandwidth
                    XmlAttribute siteUsageAttrBandwidth = xmlDocument.CreateAttribute("Bandwidth");
                    siteUsageAttrBandwidth.Value = site.Usage.Bandwidth.ToString();
                    siteUsageElt.Attributes.Append(siteUsageAttrBandwidth);
                    // DiscussionStorage
                    XmlAttribute siteUsageAttrDiscussionStorage = xmlDocument.CreateAttribute("DiscussionStorage");
                    siteUsageAttrDiscussionStorage.Value = site.Usage.DiscussionStorage.ToString();
                    siteUsageElt.Attributes.Append(siteUsageAttrDiscussionStorage);
                    // Hits
                    XmlAttribute siteUsageAttrHits = xmlDocument.CreateAttribute("Hits");
                    siteUsageAttrHits.Value = site.Usage.Hits.ToString();
                    siteUsageElt.Attributes.Append(siteUsageAttrHits);
                    // Storage
                    XmlAttribute siteUsageAttrStorage = xmlDocument.CreateAttribute("Storage");
                    siteUsageAttrStorage.Value = site.Usage.Storage.ToString();
                    siteUsageElt.Attributes.Append(siteUsageAttrStorage);
                    // Visits
                    XmlAttribute siteUsageAttrVisits = xmlDocument.CreateAttribute("Visits");
                    siteUsageAttrVisits.Value = site.Usage.Visits.ToString();
                    siteUsageElt.Attributes.Append(siteUsageAttrVisits);
                    
                    siteElt.AppendChild(siteUsageElt);

                    // for each web
                    XmlNode websElt = xmlDocument.CreateNode(XmlNodeType.Element, "Webs", "");
                    siteElt.AppendChild(websElt);
                    foreach (SPWeb web in site.AllWebs)
                    {
                        XmlNode webElt = xmlDocument.CreateNode(XmlNodeType.Element, "Web", "");
                        // ID
                        XmlAttribute webAttrID = xmlDocument.CreateAttribute("ID");
                        webAttrID.Value = web.ID.ToString();
                        webElt.Attributes.Append(webAttrID);
                        // Url
                        XmlAttribute webAttrUrl = xmlDocument.CreateAttribute("Url");
                        webAttrUrl.Value = web.Url;
                        webElt.Attributes.Append(webAttrUrl);
                        // Title
                        XmlAttribute webAttrTitle = xmlDocument.CreateAttribute("Title");
                        webAttrTitle.Value = web.Title;
                        webElt.Attributes.Append(webAttrTitle);
                        // WebTemplate
                        XmlAttribute webAttrWebTemplate = xmlDocument.CreateAttribute("WebTemplate");
                        webAttrWebTemplate.Value = web.WebTemplate;
                        webElt.Attributes.Append(webAttrWebTemplate);
                        // WebTemplateId
                        XmlAttribute webAttrWebTemplateId = xmlDocument.CreateAttribute("WebTemplateId");
                        webAttrWebTemplateId.Value = web.WebTemplateId.ToString();
                        webElt.Attributes.Append(webAttrWebTemplateId);
                        // Created
                        XmlAttribute webAttrCreated = xmlDocument.CreateAttribute("Created");
                        webAttrCreated.Value = web.Created.ToString("s");
                        webElt.Attributes.Append(webAttrCreated);
                        // Language
                        XmlAttribute webAttrLanguage = xmlDocument.CreateAttribute("Language");
                        webAttrLanguage.Value = web.Language.ToString();
                        webElt.Attributes.Append(webAttrLanguage);
                        // Theme
                        XmlAttribute webAttrTheme = xmlDocument.CreateAttribute("Theme");
                        webAttrTheme.Value = web.Theme;
                        webElt.Attributes.Append(webAttrTheme);
                        // LastItemModifiedDate
                        XmlAttribute webAttrLastItemModifiedDate = xmlDocument.CreateAttribute("LastItemModifiedDate");
                        webAttrLastItemModifiedDate.Value = web.LastItemModifiedDate.ToString("s");
                        webElt.Attributes.Append(webAttrLastItemModifiedDate);
                        // NoCrawl
                        XmlAttribute webAttrNoCrawl = xmlDocument.CreateAttribute("NoCrawl");
                        webAttrNoCrawl.Value = web.NoCrawl.ToString();
                        webElt.Attributes.Append(webAttrNoCrawl);
                        // for each list
                        XmlNode listsElt = xmlDocument.CreateNode(XmlNodeType.Element, "Lists", "");
                        // Count
                        XmlAttribute listsAttrCount = xmlDocument.CreateAttribute("Count");
                        listsAttrCount.Value = web.Lists.Count.ToString();
                        listsElt.Attributes.Append(listsAttrCount);
                        webElt.AppendChild(listsElt);
                        foreach (SPList list in web.Lists)
                        {
                            XmlNode listElt = xmlDocument.CreateNode(XmlNodeType.Element, "List", "");
                            // ID
                            XmlAttribute listAttrID = xmlDocument.CreateAttribute("ID");
                            listAttrID.Value = list.ID.ToString();
                            listElt.Attributes.Append(listAttrID);
                            // Title
                            XmlAttribute listAttrTitle = xmlDocument.CreateAttribute("Title");
                            listAttrTitle.Value = list.Title;
                            listElt.Attributes.Append(listAttrTitle);
                            // EnableSyndication
                            XmlAttribute listAttrEnableSyndication = xmlDocument.CreateAttribute("EnableSyndication");
                            listAttrEnableSyndication.Value = list.EnableSyndication.ToString();
                            listElt.Attributes.Append(listAttrEnableSyndication);
                            // BaseTemplate
                            XmlAttribute listAttrBaseTemplate = xmlDocument.CreateAttribute("BaseTemplate");
                            listAttrBaseTemplate.Value = list.BaseTemplate.ToString();
                            listElt.Attributes.Append(listAttrBaseTemplate);
                            // BaseType
                            XmlAttribute listAttrBaseType = xmlDocument.CreateAttribute("BaseType");
                            listAttrBaseType.Value = list.BaseType.ToString();
                            listElt.Attributes.Append(listAttrBaseType);
                            // HasUniqueRoleAssignments
                            XmlAttribute listAttrHasUniqueRoleAssignments = xmlDocument.CreateAttribute("HasUniqueRoleAssignments");
                            listAttrHasUniqueRoleAssignments.Value = list.HasUniqueRoleAssignments.ToString();
                            listElt.Attributes.Append(listAttrHasUniqueRoleAssignments);
                            // ContentTypesEnabled
                            XmlAttribute listAttrContentTypesEnabled = xmlDocument.CreateAttribute("ContentTypesEnabled");
                            listAttrContentTypesEnabled.Value = list.ContentTypesEnabled.ToString();
                            listElt.Attributes.Append(listAttrContentTypesEnabled);
                            // EmailAlias
                            XmlAttribute listAttrEmailAlias = xmlDocument.CreateAttribute("EmailAlias");
                            listAttrEmailAlias.Value = list.EmailAlias;
                            listElt.Attributes.Append(listAttrEmailAlias);
                            // EnableVersioning
                            XmlAttribute listAttrEnableVersioning = xmlDocument.CreateAttribute("EnableVersioning");
                            listAttrEnableVersioning.Value = list.EnableVersioning.ToString();
                            listElt.Attributes.Append(listAttrEnableVersioning);
                            // Hidden
                            XmlAttribute listAttrHidden = xmlDocument.CreateAttribute("Hidden");
                            listAttrHidden.Value = list.Hidden.ToString();
                            listElt.Attributes.Append(listAttrHidden);
                            // NoCrawl
                            XmlAttribute listAttrNoCrawl = xmlDocument.CreateAttribute("NoCrawl");
                            listAttrNoCrawl.Value = list.NoCrawl.ToString();
                            listElt.Attributes.Append(listAttrNoCrawl);
                            // ItemCount
                            XmlAttribute listAttrItemCount = xmlDocument.CreateAttribute("ItemCount");
                            listAttrItemCount.Value = list.ItemCount.ToString();
                            listElt.Attributes.Append(listAttrItemCount);
                            // Add to <Lists/> node                           
                            listsElt.AppendChild(listElt);
                        }
                        // Clean up memory
                        web.Dispose();
                        // add to parent
                        websElt.AppendChild(webElt);
                    }
                    // Clean up memory
                    site.Dispose();
                    // Append to <Sites />
                    sitesElt.AppendChild(siteElt);
                    // Set progression
                    totalSiteProgress += siteProgressStep;
                    if (totalSiteProgress <= webAppProgressStep) AddProgress(siteProgressStep);
                }

                // Append to <WebApplications />
                webAppsElt.AppendChild(webAppElt);
                // Set progression
                AddProgress(webAppProgressStep);
            }

            return xmlDocument;
        }
    }
}
